iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 23
0
自我挑戰組

前端菜焦阿日記系列 第 23

|D23| JS - `<script>` 的 async 和 defer 屬性

  • 分享至 

  • xImage
  •  
tags: 2019年鐵人賽JS

由外部引入檔案時要注意加載順序

  1. 放在 <head>
<html>
  <head> 
      ...
      <script src="./js/test.js">
      ...
  </head>
  <body>
      ...
  </body>
</html>

瀏覽器是這麼解讀 document 的,解析一部分 HTML 後暫停,加載和執行 js 後,再繼續解析 HTML


圖片來源:Asynchronous vs Deferred JavaScript

  1. async 屬性(此屬性只適用在外部引入的檔案)
<html>
  <head> 
      ...
      <script async src="./js/jquery.js"></script>
      <script async src="./js/test1.js"></script>
      <script async src="js/test2.js"></script>
      ...
  </head>
  <body>
      ...
  </body>
</html>

async 屬性告訴瀏覽器可以異步執行(executed asynchronously),
在 HTML 還在解析時加載 js,完全下載後才暫停解析 HTML ,執行 js。
https://ithelp.ithome.com.tw/upload/images/20181107/2011215893NafDwotk.png
圖片來源:Asynchronous vs Deferred JavaScript

但要注意的是 jquery.js 有可能在 test1.js 和 test2.js 之前或之後加載,順序無法確定,所以如果 test1.js 和 test2.js 裡有使用 jquery 的任何 function 都會出錯

  1. defer 屬性(此屬性只適用在外部引入的檔案)
<html>
  <head> 
      ...
      <script defer src="./js/jquery.js"></script>
      <script defer src="./js/test1.js"></script>
      <script defer src="js/test2.js"></script>
      ...
  </head>
  <body>
      ...
  </body>
</html>

defer 屬性告訴瀏覽器在 HTML 還在解析時加載 js,但是等到 HTML 整個解析完才執行 js。
https://ithelp.ithome.com.tw/upload/images/20181107/20112158jp9SHRameP.png
圖片來源:Asynchronous vs Deferred JavaScript

有defer 屬性的 js 檔會照頁面出現的順序執行

下面範例是透過 js 產生 10 個 <button> 標籤

//HTML body 區
<div id="buttons"></div>
<p></p>
//JS 檔
function showText(i){
  let pTag = document.querySelector('p');
  pTag.textContent = `按${i+1}`;
}

let divTag = document.querySelector('div');
for(let j = 1; j <= 10; j++){
  let btnTag = document.createElement('button');
  btnTag.textContent = `按${j}`;
  divTag.appendChild(btnTag);
}

let btns = document.querySelectorAll('button');
for(let i = 0; i < btns.length; i++){
  btns[i].addEventListener('click',function(){showText(i)});
}

如果放在 <head> 區會造成 js 已經 run 完,所以解析到 HTML body 時只會渲染 <div><p> 標籤而已。

解決方法

  1. 調換順序
<html>
  <head> 
      ...
  </head>
  <body>
      ...
      ...
      <script src="./js/button.js">
  </body>
</html>
  1. 使用 async 或 defer 屬性

上一篇
|D22| JS - 用 JS 產生 HTML Tag
下一篇
|D24| CSS - 偽元素 ::before 和 ::after
系列文
前端菜焦阿日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言